package com.pzr.soccer.config.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.RoleHierarchyVoter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import org.springframework.util.FileCopyUtils;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.
				cors()
				.and()
				.csrf().disable()// 使用了jwt，可以disable csrf
				.sessionManagement().disable()// 使用了jwt，可以disable session
			    .authorizeRequests()
			    .accessDecisionManager(defaultOauthDecisionManager())
			    //.expressionHandler(webExpressionHandler()) // 把spring security config的一些信息传递进来
				
				.antMatchers("/user/registry",
						"/user/login",
						"/user/reLogin",
						"/user/validation/**",
						"/user/setPassword*",
						"/user/fetchUsername*"

				/*
				 * "/sms/sendTo", "/gt/register", "/login", "/v2/api-docs",
				 * "/swagger-resources/configuration/ui",//用来获取支持的动作
				 * "/swagger-resources",//用来获取api-docs的URI
				 * "/swagger-resources/configuration/security",//安全选项 "/webjars/**",
				 * "/swagger-ui.html", "/test/**"
				 */
				).permitAll()
				.antMatchers("/**/dbAdmin/**").hasRole("DBAdmin")
				.antMatchers("/**/admin/**").hasRole("Admin")
				.antMatchers("/**/superVip/**").hasRole("SuperVip")
				.antMatchers("/**/vip/**").hasRole("Vip")
				.antMatchers("/**/normal/**").hasRole("Normal")
				.antMatchers("/**").authenticated()
				.and()
				.headers().cacheControl();
	}

	/**
	 * 设置公钥
	 *
	 * @param resources
	 * @throws Exception
	 */
	@Override
	public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
		resources.tokenStore(jwtTokenStore());

	}

	private TokenStore jwtTokenStore() {
		return new JwtTokenStore(accessTokenConverter());
	}

	@Bean // 放在ioc容器的
	public JwtAccessTokenConverter accessTokenConverter() {
		// resource 验证token（公钥） authorization 产生 token （私钥）
		JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
		String s = null;
		try {
			ClassPathResource classPathResource = new ClassPathResource("soccer.txt");
			byte[] bytes = FileCopyUtils.copyToByteArray(classPathResource.getInputStream());
			s = new String(bytes, StandardCharsets.UTF_8);
		} catch (Exception e) {
			e.printStackTrace();
		}
		tokenConverter.setVerifierKey(s);
		DefaultAccessTokenConverter defaultAccessTokenConverter = new DefaultAccessTokenConverter();

		UserAuthenticationConverter extractAuthenticationConverter = new ExtractAuthenticationConverter();
		defaultAccessTokenConverter.setUserTokenConverter(extractAuthenticationConverter);
		tokenConverter.setAccessTokenConverter(defaultAccessTokenConverter);
		return tokenConverter;
	}


	
	
	
	
	@Bean
	public RoleHierarchy roleHierarchy() {
		RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
		roleHierarchy.setHierarchy(
				"ROLE_DBAdmin > ROLE_Admin \n ROLE_Admin > ROLE_SuperVip \n ROLE_SuperVip > ROLE_Vip \n ROLE_Vip > ROLE_Normal \n ROLE_Normal > ROLE_Guest");
		return roleHierarchy;

	}

	@Bean
	public AffirmativeBased defaultOauthDecisionManager() { //

		List<AccessDecisionVoter<?>> decisionVoters = new ArrayList<>();

		// webExpressionVoter
		OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();
		expressionHandler.setRoleHierarchy(roleHierarchy());
		WebExpressionVoter webExpressionVoter = new WebExpressionVoter();
		webExpressionVoter.setExpressionHandler(expressionHandler);
		decisionVoters.add(webExpressionVoter);
		decisionVoters.add(roleVoter());
		return new AffirmativeBased(decisionVoters);
	}

	@Bean
	public RoleHierarchyVoter roleVoter() {
		return new RoleHierarchyVoter(roleHierarchy());
	}

}
